//****************************************************************************************
//
// Header file for the exported managed class representing Checkers Board engine interface
//
//****************************************************************************************

#pragma once

#include "Conversion.h"

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Threading;

// worker events
#define WORKER_COMPUTE_MOVE			0
#define WORKER_TERMINATE			1
#define WORKER_THREAD_EXITED		2
#define WORKER_MOVE_COMPUTED		3

#define WORKER_EVENT_INDEX			0
#define WORKER_EVENT_COUNT			4

namespace CheckersBoardEngine {


	// synchronization struct of BackgroundWorker thread
	struct CBWorkerSynch 
	{
	public:
		HANDLE hEvents[WORKER_EVENT_COUNT];
	};

	// CB Engine Busy exception
	public ref class CBEngineBusyException: Exception {
	};

	// Computed move event arguments
	public ref class ComputedMoveEventArgs: EventArgs
	{
	public:
		ComputedMove^ Move;
	};

	// The main engine class
	public ref class CBEngine {

	public:
		// constructor
		CBEngine(String^ enginePath);

		// event raised when computing of the move has finished
		event EventHandler<ComputedMoveEventArgs^>^ MoveComputed;
		
		// releasing the engine and clean up
		void Terminate();

		// checks, if engine is computing the move
		bool IsEngineBusy();

		// returns the progress of computing the move
		String^ GetEngineInfo();

		// returns the engine name
		String^ GetEngineName();

		// returns the code of supported checkers - code according to the PDN 3.0 standard
		int GetCheckersType();

		// starts the computing of the move
		void ComputeMove(CBGameRecord^ rec);

		// get engine options
		void GetEngineOptions([Out] EngineOptions^% opts, [Out] EngineMoreOptions^% optsMore);

		// set engine options
		void SetEngineOptions(EngineOptions^ opts, EngineMoreOptions^ optsMore);


	private:
		// thread communication class
		CBThreadParams* m_pParams;
		CBWorkerSynch* m_pSynch;

		// background worker thread
		Thread^ _backgroundThread;
		void BackgroundThreadWorker();

		// cleans up internal variables
		void CleanUp();
		void InitWorkerEvents();
		void CloseWorkerEvents();


	};
}